﻿using HslCommunication;
using HslCommunication.Core;
using HslCommunication.Core.Net;
using HslCommunication.Profinet.Keyence;
using MyLogPC.SQLs;
using MyLogPC.Config;
using MyLogPC.Logging;
using MyLogPC.PLCs.DataCollection;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace MyLogPC.PLCs
{
    internal class PLCDataExchange : IDisposable
    {
        #region 静态属性和字段
        /// <summary>
        /// PLC通用对象
        /// </summary>
        public static List<HslCommunication.Core.IReadWriteDevice>? MyPLC_List { get; set; } = new List<HslCommunication.Core.IReadWriteDevice>();

        /// <summary>
        /// 数据采集管理器
        /// </summary>
        private static DataCollectionManager? _dataCollectionManager;

        // 保留原有的静态属性，用于向后兼容
        /// <summary>
        /// 轴位置数组对象（已弃用，建议使用DataCollectionManager）
        /// </summary>
        [Obsolete("请使用 DataCollectionManager 进行数据采集")]
        public static ObservableArray<int>? PLCDataAxisPosition { get; set; }

        [Obsolete("请使用 DataCollectionManager 进行数据采集")]
        public static ObservableArray<bool> PLCDataIO { get; set; } = new ObservableArray<bool>(100);

        [Obsolete("请使用 DataCollectionManager 进行数据采集")]
        public static ObservableArray<bool> PLCDataAlarm { get; set; } = new ObservableArray<bool>(100);

        /// <summary>
        /// 轴位置地址列表（已弃用，建议使用DataCollectionManager）
        /// </summary>
        [Obsolete("地址管理已集成到各个数据采集器中")]
        public static List<Model.AxisPositionAddressModel> AxisPositionAddressList { get; set; } = new List<Model.AxisPositionAddressModel>();

        /// <summary>
        /// IO地址列表（已弃用，建议使用DataCollectionManager）
        /// </summary>
        [Obsolete("地址管理已集成到各个数据采集器中")]
        public static List<Model.IOAddressModel> IOAddressList { get; set; } = new List<Model.IOAddressModel>();

        [Obsolete("地址管理已集成到各个数据采集器中")]
        public static List<Model.AlarmAddressModel> AlarmAddressList { get; set; } = new List<Model.AlarmAddressModel>();
        #endregion

        #region 私有字段
        private static bool _isOnline = true;
        private static bool _isRunning = false;
        private static readonly LogManager _logger = LogManager.Instance;
        private static AppConfig _config = ConfigManager.GetConfig();
        #endregion

        #region 配置方法
        /// <summary>
        /// 重新加载配置
        /// </summary>
        public static void ReloadConfig()
        {
            ConfigManager.ReloadConfig();
            _config = ConfigManager.GetConfig();
            _dataCollectionManager?.ReloadConfig();
            _logger.Info("配置已重新加载", "PLCDataExchange");
        }

        /// <summary>
        /// 设置轮询间隔
        /// </summary>
        /// <param name="intervalMs">间隔时间（毫秒）</param>
        public static void SetPollingInterval(int intervalMs)
        {
            if (intervalMs > 0)
            {
                _config.DataCollection.PollingInterval = intervalMs;
                _logger.Info($"轮询间隔已设置为 {intervalMs} 毫秒", "PLCDataExchange");
            }
        }

        /// <summary>
        /// 设置连接超时时间
        /// </summary>
        /// <param name="timeoutMs">超时时间（毫秒）</param>
        public static void SetConnectionTimeout(int timeoutMs)
        {
            if (timeoutMs > 0)
            {
                _config.Plc.ConnectionTimeout = timeoutMs;
                _logger.Info($"连接超时已设置为 {timeoutMs} 毫秒", "PLCDataExchange");
            }
        }
        #endregion

        #region 公共方法
        /// <summary>
        /// 初始化PLC
        /// </summary>
        /// <param name="linkParameters">连接参数，格式为 "命名空间.类名;参数1;参数2..._连接类型参数"</param>
        /// <exception cref="ArgumentException">当创建PLC实例失败时抛出</exception>
        public static async Task<bool> InitPLCAsync(string? linkParameters = null)
        {
            try
            {
                //清空PLC连接
                MyPLC_List.Clear();
                // 使用传入参数或配置文件中的参数
                linkParameters = linkParameters ?? _config.Plc.ConnectionParameters;
                linkParameters = "HslCommunication.Profinet." + linkParameters;

                var obj = CreatePLCFromString(linkParameters);
                if (obj is HslCommunication.Core.IReadWriteDevice device)
                {
                    if (device is HslCommunication.Core.Device.DeviceTcpNet devTCP)
                    {
                        MyPLC_List.Add(devTCP);
                        var connectResult = await devTCP.ConnectServerAsync();
                        if (connectResult.IsSuccess)
                        {
                            // 初始化数据采集管理器
                            _dataCollectionManager = new DataCollectionManager();
                            return await _dataCollectionManager.InitializeAsync(device);
                        }
                        return false;
                    }
                    MyPLC_List?.Add(device);
                    
                    // 初始化数据采集管理器
                    _dataCollectionManager = new DataCollectionManager();
                    return await _dataCollectionManager.InitializeAsync(device);
                }
                else
                {
                    throw new ArgumentException("无法创建指定类型的PLC实例，请检查输入格式。");
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"初始化PLC失败：{linkParameters}", ex, "PLCDataExchange");
                return false;
            }
        }

        /// <summary>
        /// 启动PLC工作线程
        /// </summary>
        public static async Task StartPLCWorkerAsync()
        {
            if (_isRunning)
            {
                _logger.Info("PLC工作线程已在运行中", "PLCDataExchange");
                return;
            }

            if (MyPLC_List == null || MyPLC_List.Count == 0)
            {
                _logger.Error("PLC工作线程启动失败：没有可用的PLC实例", null, "PLCDataExchange");
                return;
            }

            if (_dataCollectionManager == null)
            {
                _logger.Error("数据采集管理器未初始化", null, "PLCDataExchange");
                return;
            }

            try
            {
                DbHelper.CheckDb(); // 检查数据存取数据库是否存在，不存在则创建

                // 启动数据采集管理器
                if (await _dataCollectionManager.StartAsync())
                {
                    _isRunning = true;
                    _logger.Info("PLC工作线程启动成功", "PLCDataExchange");
                }
                else
                {
                    _logger.Error("启动数据采集管理器失败", null, "PLCDataExchange");
                }
            }
            catch (Exception ex)
            {
                _logger.Error("启动PLC工作线程时发生错误", ex, "PLCDataExchange");
                _isRunning = false;
            }
        }

        /// <summary>
        /// 停止PLC工作线程
        /// </summary>
        public static void StopPLCWorker()
        {
            try
            {
                _isRunning = false;
                _dataCollectionManager?.Stop();
                _logger.Info("PLC工作线程已停止", "PLCDataExchange");
            }
            catch (Exception ex)
            {
                _logger.Error("停止PLC工作线程时发生错误", ex, "PLCDataExchange");
            }
        }

        /// <summary>
        /// 获取连接状态
        /// </summary>
        /// <returns></returns>
        public static bool IsOnline => _dataCollectionManager?.IsOnline ?? _isOnline;

        /// <summary>
        /// 获取运行状态
        /// </summary>
        /// <returns></returns>
        public static bool IsRunning => _dataCollectionManager?.IsRunning ?? _isRunning;

        /// <summary>
        /// 获取所有数据采集器状态
        /// </summary>
        /// <returns></returns>
        public static List<DataCollectorStatus> GetCollectorStatuses()
        {
            return _dataCollectionManager?.GetCollectorStatuses() ?? new List<DataCollectorStatus>();
        }

        /// <summary>
        /// 动态添加数据采集器
        /// </summary>
        /// <param name="collectorType">采集器类型</param>
        /// <returns></returns>
        public static async Task<bool> AddDataCollectorAsync(string collectorType)
        {
            if (_dataCollectionManager == null)
            {
                _logger.Error("数据采集管理器未初始化", null, "PLCDataExchange");
                return false;
            }

            return await _dataCollectionManager.AddCollectorAsync(collectorType);
        }

        /// <summary>
        /// 移除数据采集器
        /// </summary>
        /// <param name="dataTypeName">数据类型名称</param>
        /// <returns></returns>
        public static bool RemoveDataCollector(string dataTypeName)
        {
            if (_dataCollectionManager == null)
            {
                _logger.Error("数据采集管理器未初始化", null, "PLCDataExchange");
                return false;
            }

            return _dataCollectionManager.RemoveCollector(dataTypeName);
        }

        /// <summary>
        /// 注册自定义数据采集器
        /// </summary>
        /// <param name="collectorType">采集器类型</param>
        /// <param name="creator">创建函数</param>
        public static void RegisterCustomCollector(string collectorType, Func<IDataCollector> creator)
        {
            DataCollectorFactory.RegisterCollector(collectorType, creator);
        }
        #endregion

        #region 保留的兼容性方法（已弃用）
        [Obsolete("请使用新的DataCollectionManager架构")]
        private static async Task DataInitAsync()
        {
            // 保持向后兼容，但建议使用新架构
            _logger.Warning("使用了已弃用的DataInitAsync方法，建议使用新的DataCollectionManager架构", "PLCDataExchange");
        }

        [Obsolete("请使用新的DataCollectionManager架构")]
        private static void DataInit()
        {
            var task = DataInitAsync();
            task.Wait();
        }

        [Obsolete("请使用新的DataCollectionManager架构")]
        private static async Task GetAxisPositionDataAsync()
        {
            _logger.Warning("使用了已弃用的GetAxisPositionDataAsync方法", "PLCDataExchange");
        }

        [Obsolete("请使用新的DataCollectionManager架构")]
        private static async Task GetIODataAsync()
        {
            _logger.Warning("使用了已弃用的GetIODataAsync方法", "PLCDataExchange");
        }

        [Obsolete("请使用新的DataCollectionManager架构")]
        public static async Task GetAlarmDataAsync()
        {
            _logger.Warning("使用了已弃用的GetAlarmDataAsync方法", "PLCDataExchange");
        }

        [Obsolete("请使用新的DataCollectionManager架构")]
        private static void AxisPositionChanged(object? sender, ArrayChangedEventArgs<int> e)
        {
            _logger.Warning("使用了已弃用的AxisPositionChanged方法", "PLCDataExchange");
        }

        [Obsolete("请使用新的DataCollectionManager架构")]
        private static void IOChanged(object? sender, ArrayChangedEventArgs<bool> e)
        {
            _logger.Warning("使用了已弃用的IOChanged方法", "PLCDataExchange");
        }

        [Obsolete("请使用新的DataCollectionManager架构")]
        private static void AlarmChanged(object? sender, ArrayChangedEventArgs<bool> e)
        {
            _logger.Warning("使用了已弃用的AlarmChanged方法", "PLCDataExchange");
        }
        #endregion

        #region 现有的PLC创建相关方法（保持不变，但使用新的日志系统）
        public static object? CreatePLCFromString(string input)
        {
            if (string.IsNullOrWhiteSpace(input))
            {
                _logger.Error("创建PLC失败：输入字符串为空", null, "PLCDataExchange");
                return null;
            }

            try
            {
                // 解析连接类型和参数
                ConnectionInfo connectionInfo = ParseConnectionInfo(input);
                if (connectionInfo.IsValid == false)
                {
                    _logger.Error($"创建PLC失败：无效的连接参数 '{input}'", null, "PLCDataExchange");
                    return null;
                }

                // 创建PLC实例
                var plcInstance = CreatePLCInstance(connectionInfo);
                if (plcInstance == null)
                {
                    _logger.Error($"创建PLC失败：无法实例化类 '{connectionInfo.ClassName}'", null, "PLCDataExchange");
                    return null;
                }

                // 配置连接
                ConfigureConnection(plcInstance, connectionInfo);

                return plcInstance;
            }
            catch (Exception ex)
            {
                _logger.Error($"创建PLC时发生异常: {ex.Message}", ex, "PLCDataExchange");
                return null;
            }
        }

        private class ConnectionInfo
        {
            public string ClassName { get; set; } = string.Empty;
            public string[] ConstructorArgs { get; set; } = Array.Empty<string>();
            public ConnectionType Type { get; set; } = ConnectionType.Unknown;
            public string ComPort { get; set; } = string.Empty;
            public int BaudRate { get; set; } = 9600;
            public string NetworkInfo { get; set; } = string.Empty;
            public bool IsValid => !string.IsNullOrWhiteSpace(ClassName) && Type != ConnectionType.Unknown;
        }

        private enum ConnectionType
        {
            Unknown,
            Serial,
            Network
        }

        private static ConnectionInfo ParseConnectionInfo(string input)
        {
            var result = new ConnectionInfo();

            // 按下划线分割，获取类名+参数 和 连接类型参数
            var parts = input.Split('_');
            string classNameAndParameters = parts[0];

            // 确定连接类型和相关参数
            if (parts.Length > 1)
            {
                if (parts[1].Contains("COM"))
                {
                    result.Type = ConnectionType.Serial;
                    var comParts = parts[1].Split(';');
                    if (comParts.Length > 0)
                    {
                        result.ComPort = comParts[0];
                        if (comParts.Length > 1 && int.TryParse(comParts[1], out var baudRate))
                        {
                            result.BaudRate = baudRate;
                        }
                    }
                }
                else if (parts[1].Contains("NET"))
                {
                    result.Type = ConnectionType.Network;
                    result.NetworkInfo = parts[1];
                }
            }
            else if (!string.IsNullOrEmpty(classNameAndParameters))
            {
                // 如果没有连接类型参数，根据类名自动判断
                if (classNameAndParameters.Contains("Serial"))
                {
                    result.Type = ConnectionType.Serial;
                    // 使用默认串口设置
                }
                else
                {
                    result.Type = ConnectionType.Network;
                    // 假设其他都是网络连接
                }
            }

            // 解析类名和构造函数参数
            var linkParts = classNameAndParameters.Split(';');
            if (linkParts.Length > 0)
            {
                result.ClassName = linkParts[0];
                result.ConstructorArgs = linkParts.Skip(1).ToArray();
            }

            return result;
        }

        private static object? CreatePLCInstance(ConnectionInfo connectionInfo)
        {
            // 查找类型
            var type = FindType(connectionInfo.ClassName);
            if (type == null) return null;

            // 尝试创建实例
            return InstantiateWithMatchingConstructor(type, connectionInfo.ConstructorArgs);
        }

        private static Type? FindType(string className)
        {
            // 直接尝试获取类型
            var type = Type.GetType(className);
            if (type != null) return type;

            // 从所有已加载的程序集中查找
            foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = asm.GetType(className);
                if (type != null) return type;
            }

            return null;
        }

        private static object? InstantiateWithMatchingConstructor(Type type, string[] ctorArgs)
        {
            // 获取所有构造函数
            var ctors = type.GetConstructors();

            foreach (var ctor in ctors)
            {
                var parameters = ctor.GetParameters();
                if (parameters.Length != ctorArgs.Length) continue;

                try
                {
                    // 尝试将字符串参数转换为目标类型
                    object?[] convertedArgs = new object?[parameters.Length];
                    bool allParamsConvertible = true;

                    for (int i = 0; i < parameters.Length; i++)
                    {
                        var paramType = parameters[i].ParameterType;
                        try
                        {
                            if (paramType.IsEnum)
                            {
                                convertedArgs[i] = Enum.Parse(paramType, ctorArgs[i]);
                            }
                            else
                            {
                                convertedArgs[i] = Convert.ChangeType(ctorArgs[i], paramType);
                            }
                        }
                        catch
                        {
                            allParamsConvertible = false;
                            break;
                        }
                    }

                    if (!allParamsConvertible) continue;

                    // 创建实例
                    return ctor.Invoke(convertedArgs);
                }
                catch (Exception ex)
                {
                    _logger.Error($"实例化类型 {type.Name} 时出错", ex, "PLCDataExchange");
                    // 尝试下一个构造函数
                }
            }

            return null;
        }

        private static void ConfigureConnection(object plcInstance, ConnectionInfo connectionInfo)
        {
            try
            {
                // 配置串口设备
                if (connectionInfo.Type == ConnectionType.Serial &&
                    plcInstance is HslCommunication.Core.IReadWriteDevice device &&
                    plcInstance is HslCommunication.Core.Device.DeviceSerialPort serialPort)
                {
                    serialPort.SerialPortInni(connectionInfo.ComPort, connectionInfo.BaudRate);
                }
                // NET设备无需配置，已在构造函数中处理
            }
            catch (Exception ex)
            {
                _logger.Error($"配置PLC连接时出错", ex, "PLCDataExchange");
            }
        }
        #endregion

        #region IDisposable实现
        public void Dispose()
        {
            StopPLCWorker();
            _dataCollectionManager?.Dispose();
        }
        #endregion
    }
}
